﻿
package extremefx.crypto.hash {
		
	/**
	 * @author Marcelo Volmaro
	 */
	public final class SHA1 extends SHABase implements IHash{

		public override function getHashSize():uint {
			return 20;
		}
		
		protected override function core(x:Array, len:uint):Array {
		  /* append padding */
		  x[len >> 5] |= 0x80 << (24 - len % 32);
		  x[((len + 64 >> 9) << 4) + 15] = len;
		
		  var w:Array = [];
		  var a:uint =  0x67452301; //1732584193;
		  var b:uint = 0xEFCDAB89; //-271733879;
		  var c:uint = 0x98BADCFE; //-1732584194;
		  var d:uint = 0x10325476; //271733878;
		  var e:uint = 0xC3D2E1F0; //-1009589776;
		
		  for(var i:uint = 0; i < x.length; i += 16) {
		  	
		    var olda:uint = a;
		    var oldb:uint = b;
		    var oldc:uint = c;
		    var oldd:uint = d;
		    var olde:uint = e;
		
		    for(var j:uint = 0; j < 80; j++) {
		      if (j < 16) {
		      	w[j] = x[i + j] || 0;
		      } else {
		      	w[j] = _rol(w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16], 1);
		      }
		      var t:uint = _rol(a,5) + _ft(j,b,c,d) + e + w[j] + _kt(j);
		      e = d;
		      d = c;
		      c = _rol(b, 30);
		      b = a;
		      a = t;
		    }
			a += olda;
			b += oldb;
			c += oldc;
			d += oldd;
			e += olde;
		  }
		  
		  return [ a, b, c, d, e ];
		}
		
		private function _rol(num:uint, cnt:uint):uint {
		  return (num << cnt) | (num >>> (32 - cnt));
		}
		
		private function _ft(t:uint, b:uint, c:uint, d:uint):uint {
		  if(t < 20) return (b & c) | ((~b) & d);
		  if(t < 40) return b ^ c ^ d;
		  if(t < 60) return (b & c) | (b & d) | (c & d);
		  return b ^ c ^ d;
		}
		
		private function _kt(t:uint):uint {
		  return (t < 20) ? 0x5A827999 : (t < 40) ?  0x6ED9EBA1 : (t < 60) ? 0x8F1BBCDC : 0xCA62C1D6;
		}
		
		public override function toString():String {
			return "sha1";
		}
	}
}
